home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / dflat2.zip / NORMAL.C < prev    next >
Text File  |  1991-04-19  |  23KB  |  879 lines

  1. /* ------------- normal.c ------------ */
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <conio.h>
  7. #include <dos.h>
  8. #include "dflat.h"
  9.  
  10. #define ICONHEIGHT 3
  11. #define ICONWIDTH  10
  12.  
  13. int WindowMoving = FALSE;
  14. int WindowSizing = FALSE;
  15. static int dragcount = -1;
  16. static int diff;
  17. static int conditioning = FALSE;
  18. static struct window dwnd = {DUMMY, NULL, NULL, NormalProc,
  19.                                 {-1,-1,-1,-1}};
  20.  
  21. struct LinkedList Focus = {NULLWND, NULLWND};
  22. struct LinkedList Built = {NULLWND, NULLWND};
  23. static WINDOW NextWindow;
  24.  
  25. static void TerminateMoveSize(void);
  26. static void near PaintOverLappers(WINDOW wnd);
  27. static void near dragborder(WINDOW, int, int);
  28. static void near sizeborder(WINDOW, int, int);
  29. static void SaveBorder(RECT);
  30. static void RestoreBorder(RECT);
  31. static void RemoveWindow(WINDOW, int);
  32. static void AddWindow(WINDOW, int);
  33. static int InsideWindow(WINDOW, int, int);
  34. static RECT PositionIcon(WINDOW);
  35.  
  36. static int px = -1, py = -1;
  37. static int CloseDepth = 0;
  38.  
  39. int NormalProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  40. {
  41.     int    mx = (int) p1 - GetLeft(wnd);
  42.     int    my = (int) p2 - GetTop(wnd);
  43.     switch (msg)    {
  44.         case CREATE_WINDOW:
  45.             AddWindow(wnd, TRUE);
  46.             if (!SendMessage(NULLWND, MOUSE_INSTALLED, 0, 0))
  47.                 ClearAttribute(wnd, VSCROLLBAR | HSCROLLBAR);
  48.             if (TestAttribute(wnd, SAVESELF) && isVisible(wnd))
  49.                 GetVideoBuffer(wnd);
  50.             break;
  51.         case SHOW_WINDOW:
  52.             if ((GetParent(wnd) == NULLWND ||
  53.                         isVisible(GetParent(wnd))) && !conditioning)    {
  54.                 WINDOW cwnd = Focus.FirstWindow;
  55.                 if (TestAttribute(wnd, SAVESELF) && wnd->videosave == NULL)
  56.                     GetVideoBuffer(wnd);
  57.                 SetVisible(wnd);
  58.                 SendMessage(wnd, PAINT, 0, 0);
  59.                 SendMessage(wnd, BORDER, 0, 0);
  60.                 while (cwnd != NULLWND)    {
  61.                     if (GetParent(cwnd) == wnd)
  62.                         SendMessage(cwnd, msg, p1, p2);
  63.                     cwnd = NextWindow(cwnd);
  64.                 }
  65.             }
  66.             break;
  67.         case HIDE_WINDOW:
  68.             if (isVisible(wnd) && !conditioning)    {
  69.                 WINDOW cwnd = Focus.LastWindow;
  70.                 while (cwnd != NULLWND)    {
  71.                     if (GetParent(cwnd) == wnd)
  72.                         ClearVisible(cwnd);
  73.                     cwnd = PrevWindow(cwnd);
  74.                 }
  75.                 if (wnd->videosave != NULL)
  76.                     RestoreVideoBuffer(wnd);
  77.                 else
  78.                     PaintOverLappers(wnd);
  79.                 ClearVisible(wnd);
  80.             }
  81.             break;
  82.         case INSIDE_WINDOW:
  83.             return InsideWindow(wnd, (int) p1, (int) p2);
  84.         case KEYBOARD:
  85.             if (WindowMoving || WindowSizing)    {
  86.                 int x, y;
  87.                 x = WindowMoving ? GetLeft(&dwnd) : GetRight(&dwnd);
  88.                 y = WindowMoving ? GetTop(&dwnd) : GetBottom(&dwnd);
  89.                 switch ((int)p1)    {
  90.                     case ESC:
  91.                         TerminateMoveSize();
  92.                         return TRUE;
  93.                     case UP:
  94.                         if (y)
  95.                             --y;
  96.                         break;
  97.                     case DN:
  98.                         if (y < SCREENHEIGHT-1)
  99.                             y++;
  100.                         break;
  101.                     case FWD:
  102.                         if (x < SCREENWIDTH-1)
  103.                             x++;
  104.                         break;
  105.                     case BS:
  106.                         if (x)
  107.                             --x;
  108.                         break;
  109.                     case '\r':
  110.                         SendMessage(wnd, BUTTON_RELEASED, x, y);
  111.                     default:
  112.                         return TRUE;
  113.                 }
  114.                 SendMessage(wnd, MOUSE_CURSOR, x, y);
  115.                 SendMessage(wnd, MOUSE_MOVED, x, y);
  116.                 break;
  117.             }
  118.             PostMessage(GetParent(wnd), msg, p1, p2);
  119.             break;
  120.         case PAINT:
  121.             if (isVisible(wnd))    
  122.                 ClearWindow(wnd, (RECT *)p1, ' ');
  123.             break;
  124.         case BORDER:
  125.             if (isVisible(wnd))
  126.                 RepaintBorder(wnd, (RECT *)p1);
  127.             break;
  128.         case COMMAND:
  129.             switch ((int)p1)    {
  130.                 case ID_SYSRESTORE:
  131.                     SendMessage(wnd, RESTORE, 0, 0);
  132.                     break;
  133.                 case ID_SYSMOVE:
  134.                     SendMessage(wnd, CAPTURE_MOUSE, TRUE, (PARAM) &dwnd);
  135.                     SendMessage(wnd, CAPTURE_KEYBOARD, TRUE, (PARAM) &dwnd);
  136.                     SendMessage(wnd, MOUSE_CURSOR, GetLeft(wnd), GetTop(wnd));
  137.                     WindowMoving = TRUE;
  138.                     dragborder(wnd, GetLeft(wnd), GetTop(wnd));
  139.                     break;
  140.                 case ID_SYSSIZE:
  141.                     SendMessage(wnd, CAPTURE_MOUSE, TRUE, (PARAM) &dwnd);
  142.                     SendMessage(wnd, CAPTURE_KEYBOARD, TRUE, (PARAM) &dwnd);
  143.                     SendMessage(wnd, MOUSE_CURSOR, GetRight(wnd), GetBottom(wnd));
  144.                     WindowSizing = TRUE;
  145.                     dragborder(wnd, GetLeft(wnd), GetTop(wnd));
  146.                     break;
  147.                 case ID_SYSMINIMIZE:
  148.                     SendMessage(wnd, MINIMIZE, 0, 0);
  149.                     break;
  150.                 case ID_SYSMAXIMIZE:
  151.                     SendMessage(wnd, MAXIMIZE, 0, 0);
  152.                     break;
  153.                 case ID_SYSCLOSE:
  154.                     SendMessage(wnd, CLOSE_WINDOW, 0, 0);
  155.                     break;
  156.                 default:
  157.                     break;
  158.             }
  159.             break;
  160.         case SETFOCUS:
  161.             if (p1 && inFocus != wnd)    {
  162.                 SendMessage(inFocus, SETFOCUS, FALSE, 0);
  163.                 /* remove from list */
  164.                 RemoveWindow(wnd, FALSE);
  165.                 /* move window to end of list */
  166.                 AddWindow(wnd, FALSE);
  167.                 inFocus = wnd;
  168.                 SendMessage(wnd, SHOW_WINDOW, 0, 0);
  169.             }
  170.             else if (!p1 && inFocus == wnd)    {
  171.                 inFocus = NULL;
  172.                 SendMessage(wnd, BORDER, 0, 0);
  173.             }
  174.             break;
  175.         case DOUBLE_CLICK:
  176.             if (!SendMessage(wnd, INSIDE_WINDOW, p1, p2) &&
  177.                         CaptureMouse == NULLWND)    {
  178.                 PostMessage(GetParent(wnd), msg, p1, p2);
  179.                 break;
  180.             }
  181.             if (!WindowSizing && !WindowMoving)
  182.                 if (HitControlBox(wnd, mx, my))
  183.                     PostMessage(wnd, CLOSE_WINDOW, 0, 0);
  184.             break;
  185.         case LEFT_BUTTON:
  186.             if (WindowSizing || WindowMoving)
  187.                 return FALSE;
  188.             if ((!SendMessage(wnd, INSIDE_WINDOW, p1, p2) &&
  189.                     CaptureMouse == NULLWND) ||
  190.                         HitControlBox(wnd, mx, my))    {
  191.                 PostMessage(GetParent(wnd), msg, p1, p2);
  192.                 break;
  193.             }
  194.             if (my == 0 && TestAttribute(wnd, TITLEBAR))    {
  195.                 /* ---------- hit the title bar -------- */
  196.                 if (TestAttribute(wnd, MINMAXBOX))        {
  197.                     if (mx == WindowWidth(wnd)-2)    {
  198.                         if (wnd->condition == ISRESTORED)    {
  199.                             SendMessage(wnd, MAXIMIZE, 0, 0);
  200.                             break;
  201.                         }
  202.                         else    {
  203.                             SendMessage(wnd, RESTORE, 0, 0);
  204.                             break;
  205.                         }
  206.                     }
  207.                     else if (mx == WindowWidth(wnd)-3)    {
  208.                         if (wnd->condition != ISMINIMIZED)    {
  209.                             SendMessage(wnd, MINIMIZE, 0, 0);
  210.                             break;
  211.                         }
  212.                     }
  213.                 }
  214.             }
  215.             if ((TestAttribute(wnd, MOVEABLE) && my == 0) ||
  216.                 TestAttribute(wnd, SIZEABLE) &&
  217.                         mx == WindowWidth(wnd)-1 && my == WindowHeight(wnd)-1)    {
  218.                 if (wnd->condition == ISMAXIMIZED)
  219.                     break;
  220.                 if (my != 0 && wnd->condition == ISMINIMIZED)
  221.                     break;
  222.                 if (dragcount == -1)
  223.                     dragcount = 2;
  224.                 if (--dragcount == 0)    {
  225.                     if (px != (int)p1 || py != (int)p2)    {
  226.                         px = py = -1;
  227.                         break;
  228.                     }
  229.                     SendMessage(wnd, CAPTURE_MOUSE, TRUE, (PARAM) &dwnd);
  230.                     if (my == 0)    {
  231.                         WindowMoving = TRUE;
  232.                         px = mx;
  233.                         py = my;
  234.                         diff = (int) mx;
  235.                     }
  236.                     else
  237.                         WindowSizing = TRUE;
  238.                     dragcount = -1;
  239.                     dragborder(wnd, GetLeft(wnd), GetTop(wnd));
  240.                     return FALSE;
  241.                 }
  242.                 else {
  243.                     px = (int)p1;
  244.                     py = (int)p2;
  245.                 }
  246.             }
  247.             break;
  248.         case MOUSE_MOVED:
  249.             if (WindowMoving)    {
  250.                 int leftmost = 0, topmost = 0,
  251.                     bottommost = SCREENHEIGHT-2,
  252.                     rightmost = SCREENWIDTH-2;
  253.                 int x = (int) p1 - diff;
  254.                 int y = (int) p2;
  255.                 if (GetParent(wnd) != NULLWND)    {
  256.                     WINDOW wnd1 = GetParent(wnd);
  257.                     topmost    = GetClientTop(wnd1);
  258.                     leftmost   = GetClientLeft(wnd1);
  259.                     bottommost = GetClientBottom(wnd1);
  260.                     rightmost  = GetClientRight(wnd1)-1;
  261.                     if (TestAttribute(wnd1, HASMENUBAR))
  262.                         topmost++;
  263.                 }
  264.                 if (x < leftmost || x > rightmost ||
  265.                         y < topmost || y > bottommost)    {
  266.                     x = max(x, leftmost);
  267.                     x = min(x, rightmost);
  268.                     y = max(y, topmost);
  269.                     y = min(y, bottommost);
  270.                     SendMessage(NULLWND, MOUSE_CURSOR, x+diff, y);
  271.                 }
  272.                 if (x != px || y != py)    {
  273.                     px = x;
  274.                     py = y;
  275.                     dragborder(wnd, x, y);
  276.                 }
  277.                 return TRUE;
  278.             }
  279.             if (WindowSizing)    {
  280.                 sizeborder(wnd, (int) p1, (int) p2);
  281.                 return TRUE;
  282.             }
  283.             break;
  284.         case BUTTON_RELEASED:
  285.             if (WindowMoving || WindowSizing)    {
  286.                 if (WindowMoving)
  287.                     PostMessage(wnd, MOVE, dwnd.rc.lf, dwnd.rc.tp);
  288.                 else
  289.                     PostMessage(wnd, SIZE, dwnd.rc.rt, dwnd.rc.bt);
  290.                 TerminateMoveSize();
  291.             }
  292.             break;
  293.         case MAXIMIZE:
  294.             if (wnd->condition != ISMAXIMIZED)    {
  295.                 RECT rc = {0, 0, 0, 0};
  296.                 RECT holdrc = wnd->RestoredRC;
  297.                 rc.rt = SCREENWIDTH-1;
  298.                 rc.bt = SCREENHEIGHT-1;
  299.                 if (GetParent(wnd))
  300.                     rc = ClientRect(GetParent(wnd));
  301.                 wnd->condition = ISMAXIMIZED;
  302.                 SendMessage(wnd, HIDE_WINDOW, 0, 0);
  303.                 conditioning = TRUE;
  304.                 SendMessage(wnd, MOVE, RectLeft(rc), RectTop(rc));
  305.                 SendMessage(wnd, SIZE, RectRight(rc), RectBottom(rc));
  306.                 conditioning = FALSE;
  307.                 if (wnd->restored_attrib == 0)
  308.                     wnd->restored_attrib = wnd->attrib;
  309.                 ClearAttribute(wnd,    SHADOW | SIZEABLE);
  310.                 SendMessage(wnd, SHOW_WINDOW, 0, 0);
  311.                 wnd->RestoredRC = holdrc;
  312.             }
  313.             break;
  314.         case MINIMIZE:
  315.             if (wnd->condition != ISMINIMIZED)    {
  316.                 RECT rc;
  317.                 RECT holdrc = wnd->RestoredRC;
  318.  
  319.                 rc = PositionIcon(wnd);
  320.                 wnd->condition = ISMINIMIZED;
  321.                 SendMessage(wnd, HIDE_WINDOW, 0, 0);
  322.                 conditioning = TRUE;
  323.                 SendMessage(wnd, MOVE, RectLeft(rc), RectTop(rc));
  324.                 SendMessage(wnd, SIZE, RectRight(rc), RectBottom(rc));
  325.                 SetNextFocus(wnd, FALSE);
  326.                 conditioning = FALSE;
  327.                 if (wnd->restored_attrib == 0)
  328.                     wnd->restored_attrib = wnd->attrib;
  329.                 ClearAttribute(wnd,
  330.                     SHADOW | SIZEABLE | HASMENUBAR |
  331.                     VSCROLLBAR | HSCROLLBAR);
  332.                 SendMessage(wnd, SHOW_WINDOW, 0, 0);
  333.                 wnd->RestoredRC = holdrc;
  334.             }
  335.             break;
  336.         case RESTORE:
  337.             if (wnd->condition != ISRESTORED)    {
  338.                 RECT holdrc = wnd->RestoredRC;
  339.                 wnd->condition = ISRESTORED;
  340.                 SendMessage(wnd, HIDE_WINDOW, 0, 0);
  341.                 wnd->attrib = wnd->restored_attrib;
  342.                 wnd->restored_attrib = 0;
  343.                 conditioning = TRUE;
  344.                 SendMessage(wnd, MOVE, wnd->RestoredRC.lf,
  345.                     wnd->RestoredRC.tp);
  346.                 wnd->RestoredRC = holdrc;
  347.                 SendMessage(wnd, SIZE, wnd->RestoredRC.rt,
  348.                     wnd->RestoredRC.bt);
  349.                 SendMessage(wnd, SETFOCUS, TRUE, 0);
  350.                 conditioning = FALSE;
  351.                 SendMessage(wnd, SHOW_WINDOW, 0, 0);
  352.             }
  353.             break;
  354.         case MOVE:    {
  355.             int xdif = (int) p1 - wnd->rc.lf;
  356.             int ydif = (int) p2 - wnd->rc.tp;
  357.             WINDOW wnd1 = Focus.FirstWindow;
  358.  
  359.             SendMessage(wnd, HIDE_WINDOW, 0, 0);
  360.             wnd->rc.lf = (int) p1;
  361.             wnd->rc.tp = (int) p2;
  362.             wnd->rc.rt = GetLeft(wnd)+WindowWidth(wnd)-1;
  363.             wnd->rc.bt = GetTop(wnd)+WindowHeight(wnd)-1;
  364.             if (wnd->condition == ISRESTORED)
  365.                 wnd->RestoredRC = wnd->rc;
  366.             while (wnd1 != NULLWND)    {
  367.                 if (GetParent(wnd1) == wnd)
  368.                     SendMessage(wnd1, MOVE,
  369.                         wnd1->rc.lf+xdif, wnd1->rc.tp+ydif);
  370.                 wnd1 = NextWindow(wnd1);
  371.             }
  372.             SendMessage(wnd, SHOW_WINDOW, 0, 0);
  373.             break;
  374.         }
  375.         case SIZE:
  376.             SendMessage(wnd, HIDE_WINDOW, 0, 0);
  377.             wnd->rc.rt = (int) p1;
  378.             wnd->rc.bt = (int) p2;
  379.             wnd->ht = GetBottom(wnd)-GetTop(wnd)+1;
  380.             wnd->wd = GetRight(wnd)-GetLeft(wnd)+1;
  381.             wnd->RestoredRC = WindowRect(wnd);
  382.             SendMessage(wnd, SHOW_WINDOW, 0, 0);
  383.             break;
  384.         case CLOSE_WINDOW:
  385.             if (isWindow(wnd))    {
  386.                  int DoneClosing = FALSE;
  387.  
  388.                 /* ----------- hide this window ------------ */
  389.                 SendMessage(wnd, HIDE_WINDOW, 0, 0);
  390.  
  391.                 /* ------- close the children of this window ------- */
  392.                 CloseDepth++;
  393.                 while (!DoneClosing)    {
  394.                     WINDOW wnd1 = Focus.LastWindow;
  395.                     DoneClosing = TRUE;
  396.                     while (wnd1 != NULLWND)    {
  397.                         WINDOW prwnd = PrevWindow(wnd1);
  398.                         if (GetParent(wnd1) == wnd)    {
  399.                             SendMessage(wnd1, CLOSE_WINDOW, 0, 0);
  400.                             DoneClosing = FALSE;
  401.                             break;
  402.                         }
  403.                         wnd1 = prwnd;
  404.                     }
  405.                 }
  406.                 --CloseDepth;
  407.  
  408.                 /* ------- remove this window from the
  409.                         list of open windows ------------- */
  410.  
  411.                 RemoveWindow(wnd, TRUE);
  412.  
  413.                 /* --- change focus if this window had it --- */
  414.                 if (CloseDepth == 0)
  415.                     SetNextFocus(wnd, TRUE);
  416.                 else if (wnd == inFocus)
  417.                     inFocus = NULL;
  418.  
  419.                 /* ----- free memory allocated to this window ----- */
  420.                 if (wnd->title != NULL)
  421.                     free(wnd->title);
  422.                 if (wnd->videosave != NULL)
  423.                     free(wnd->videosave);
  424.                 free(wnd);
  425.             }
  426.             break;
  427.         default:
  428.             break;
  429.     }
  430.     return TRUE;
  431. }
  432.  
  433. static RECT LowerLeft(RECT prc)
  434. {
  435.     RECT rc;
  436.  
  437.     RectLeft(rc) = RectRight(prc) - ICONWIDTH;
  438.     RectTop(rc) = RectBottom(prc) - ICONHEIGHT;
  439.     RectRight(rc) = RectLeft(rc)+ICONWIDTH-1;
  440.     RectBottom(rc) = RectTop(rc)+ICONHEIGHT-1;
  441.     return rc;
  442. }
  443.  
  444. static RECT PositionIcon(WINDOW wnd)
  445. {
  446.     RECT rc;
  447.  
  448.     RectLeft(rc) = SCREENWIDTH-ICONWIDTH;
  449.     RectTop(rc) = SCREENHEIGHT-ICONHEIGHT;
  450.     RectRight(rc) = SCREENWIDTH-1;
  451.     RectBottom(rc) = SCREENHEIGHT-1;
  452.     if (GetParent(wnd))    {
  453.         WINDOW wnd1 = (WINDOW) -1;
  454.         RECT prc = WindowRect(GetParent(wnd));
  455.  
  456.         rc = LowerLeft(prc);
  457.  
  458.         /* - search for icon available location - */
  459.         while (wnd1 != NULLWND)    {
  460.             wnd1 = GetFirstChild(GetParent(wnd));
  461.             while (wnd1 != NULLWND)    {
  462.                 if (wnd1->condition == ISMINIMIZED)    {
  463.                     RECT rc1 = WindowRect(wnd1);
  464.                     if (RectLeft(rc1) == RectLeft(rc) &&
  465.                             RectTop(rc1) == RectTop(rc))    {
  466.                         RectLeft(rc) -= ICONWIDTH;
  467.                         RectRight(rc) -= ICONWIDTH;
  468.                         if (RectLeft(rc) < RectLeft(prc)+1)    {
  469.                             RectLeft(rc) = RectRight(prc)-ICONWIDTH;
  470.                             RectRight(rc) = RectLeft(rc)+ICONWIDTH-1;
  471.                             RectTop(rc) -= ICONHEIGHT;
  472.                             RectBottom(rc) -= ICONHEIGHT;
  473.                             if (RectTop(rc) < RectTop(prc)+1)
  474.                                 return LowerLeft(prc);
  475.                         }
  476.                         break;
  477.                     }
  478.                 }
  479.                 wnd1 = GetNextChild(GetParent(wnd));
  480.             }
  481.         }
  482.     }
  483.     return rc;
  484. }
  485.  
  486. static void TerminateMoveSize(void)
  487. {
  488.     px = py = -1;
  489.     diff = 0;
  490.     SendMessage(&dwnd, RELEASE_MOUSE, 0, 0);
  491.     SendMessage(&dwnd, RELEASE_KEYBOARD, 0, 0);
  492.     RestoreBorder(dwnd.rc);
  493.     WindowMoving = WindowSizing = FALSE;
  494. }
  495.  
  496. static void near dragborder(WINDOW wnd, int x, int y)
  497. {
  498.     RestoreBorder(dwnd.rc);
  499.     /* ------- build the dummy window -------- */
  500.     dwnd.rc.lf = x;
  501.     dwnd.rc.tp = y;
  502.     dwnd.rc.rt = dwnd.rc.lf+WindowWidth(wnd)-1;
  503.     dwnd.rc.bt = dwnd.rc.tp+WindowHeight(wnd)-1;
  504.     dwnd.ht = WindowHeight(wnd);
  505.     dwnd.wd = WindowWidth(wnd);
  506.     dwnd.parent = GetParent(wnd);
  507.     dwnd.attrib = VISIBLE | HASBORDER | NOCLIP;
  508.     SaveBorder(dwnd.rc);
  509.     DisplayBorder(&dwnd);
  510. }
  511.  
  512. static void near sizeborder(WINDOW wnd, int rt, int bt)
  513. {
  514.     int leftmost = GetLeft(wnd)+10;
  515.     int topmost = GetTop(wnd)+3;
  516.     int bottommost = SCREENHEIGHT-1;
  517.     int rightmost  = SCREENWIDTH-1;
  518.     if (GetParent(wnd))    {
  519.         bottommost = min(bottommost, GetBottom(GetParent(wnd))-1);
  520.         rightmost  = min(rightmost, GetRight(GetParent(wnd))-1);
  521.     }
  522.     rt = min(rt, rightmost);
  523.     bt = min(bt, bottommost);
  524.     rt = max(rt, leftmost);
  525.     bt = max(bt, topmost);
  526.     SendMessage(NULLWND, MOUSE_CURSOR, rt, bt);
  527.  
  528.     if (rt != px || bt != py)
  529.         RestoreBorder(dwnd.rc);
  530.  
  531.     /* ------- change the dummy window -------- */
  532.     dwnd.ht = bt-dwnd.rc.tp+1;
  533.     dwnd.wd = rt-dwnd.rc.lf+1;
  534.     dwnd.rc.rt = rt;
  535.     dwnd.rc.bt = bt;
  536.     if (rt != px || bt != py)    {
  537.         px = rt;
  538.         py = bt;
  539.         SaveBorder(dwnd.rc);
  540.         DisplayBorder(&dwnd);
  541.     }
  542. }
  543.  
  544. void SetNextFocus(WINDOW wnd, int PassParam)
  545. {
  546.     if (NextWindow(Focus.FirstWindow) == NULLWND)
  547.         inFocus = NULLWND;
  548.     else if (wnd == inFocus)    {
  549.         int loopctr = 0;
  550.         WINDOW wnd1 = wnd;
  551.         while (wnd1 != NULLWND)    {
  552.             if (NextWindow(wnd1) == NULLWND)    {
  553.                 wnd1 = Focus.FirstWindow;
  554.                 if (loopctr++)    {
  555.                     if (PassParam)
  556.                         inFocus = NULLWND;
  557.                     break;
  558.                 }
  559.             }
  560.             else
  561.                 wnd1 = NextWindow(wnd1);
  562.             if (wnd1 == wnd)
  563.                 continue;
  564.             if (GetParent(wnd1) != GetParent(wnd))
  565.                 continue;
  566.             if (SendMessage(wnd1, SETFOCUS, TRUE, PassParam))
  567.                 break;
  568.         }
  569.     }
  570. }
  571.  
  572. static void near PaintOverLap(WINDOW wnd, RECT rc)
  573. {
  574.     RECT src = rc;
  575.  
  576.     int isLF = RectLeft(rc) == GetLeft(wnd);
  577.     int isBT = RectBottom(rc) == GetBottom(wnd);
  578.     int isRT = RectRight(rc) == GetRight(wnd);
  579.     int isTP = RectTop(rc) == GetTop(wnd);
  580.     int isRSH = TestAttribute(wnd, SHADOW) &&
  581.                 RectRight(rc) == GetRight(wnd)+1;
  582.     int isBSH = TestAttribute(wnd, SHADOW) &&
  583.                 RectBottom(rc) == GetBottom(wnd)+1;
  584.     int isSH = isRSH | isBSH;
  585.  
  586.     /* ---- adjust rect to remove border intersections --- */
  587.     if (isLF)
  588.         RectLeft(rc)++;
  589.     if (isRT)
  590.         --RectRight(rc);
  591.     if (isTP)
  592.         RectTop(rc)++;
  593.     if (isBT)
  594.         --RectBottom(rc);
  595.     if (isRSH)
  596.         RectRight(rc) -= 2;
  597.     if (isBSH)
  598.         RectBottom(rc) -= 2;
  599.  
  600.     if (RectLeft(rc) <= RectRight(rc) &&
  601.             RectTop(rc) <= RectBottom(rc))    {
  602.         /* --- adjust rectangle to be relative to
  603.                 window's client area --- */
  604.         RectLeft(rc) -= GetClientLeft(wnd);
  605.         RectTop(rc) -= GetClientTop(wnd);
  606.         RectRight(rc) -= GetClientLeft(wnd);
  607.         RectBottom(rc) -= GetClientTop(wnd);
  608.  
  609.         SendMessage(wnd, PAINT, (PARAM) &rc, 0);
  610.     }
  611.  
  612.     /* -- adjust border rectangle to be relative to window's area -- */
  613.     RectLeft(src) -= GetLeft(wnd);
  614.     RectTop(src) -= GetTop(wnd);
  615.     RectRight(src) -= GetLeft(wnd);
  616.     RectBottom(src) -= GetTop(wnd);
  617.  
  618.     if (isRT || isTP || isLF || isBT || isSH)
  619.         SendMessage(wnd, BORDER, (PARAM) &src, 0);
  620. }
  621.  
  622. static RECT adjShadow(WINDOW wnd)
  623. {
  624.     RECT rc = wnd->rc;
  625.     if (TestAttribute(wnd, SHADOW))    {
  626.         if (RectRight(rc) < SCREENWIDTH-1)
  627.             RectRight(rc)++;           
  628.         if (RectBottom(rc) < SCREENHEIGHT-1)
  629.             RectBottom(rc)++;
  630.     }
  631.     return rc;
  632. }
  633.  
  634. static void near PaintOverLappers(WINDOW wnd)
  635. {
  636.     if (isVisible(wnd))    {
  637.         WINDOW lownd = Focus.FirstWindow;
  638.         RECT wrc = adjShadow(wnd);
  639.         while (lownd != NULL)    {
  640.             if (lownd != wnd && isVisible(lownd))    {
  641.                 RECT rc = adjShadow(lownd);
  642.                 rc = subRectangle(rc, wrc);
  643.                 if (ValidRect(rc))
  644.                     if (GetParent(lownd) != wnd)
  645.                         PaintOverLap(lownd, rc);
  646.             }
  647.             lownd = NextWindow(lownd);
  648.         }
  649.     }
  650. }
  651.  
  652. static int *Bsave = NULL;
  653. static int Bht, Bwd;
  654.  
  655. static void SaveBorder(RECT rc)
  656. {
  657.     Bht = RectBottom(rc) - RectTop(rc) + 1;
  658.     Bwd = RectRight(rc) - RectLeft(rc) + 1;
  659.     if ((Bsave = realloc(Bsave, (Bht + Bwd) * 4)) != NULL)    {
  660.         RECT lrc = rc;
  661.         int i;
  662.         int *cp;
  663.         RectBottom(lrc) = RectTop(lrc);
  664.         getvideo(lrc, Bsave);
  665.         RectTop(lrc) = RectBottom(lrc) = RectBottom(rc);
  666.         getvideo(lrc, Bsave + Bwd);
  667.         cp = Bsave + Bwd * 2;
  668.         for (i = 1; i < Bht-1; i++)    {
  669.             *cp++ = GetVideoChar(RectLeft(rc),RectTop(rc)+i);
  670.             *cp++ = GetVideoChar(RectRight(rc),RectTop(rc)+i);
  671.         }
  672.     }
  673. }
  674.  
  675. static void RestoreBorder(RECT rc)
  676. {
  677.     if (Bsave != NULL)    {
  678.         RECT lrc = rc;
  679.         int i;
  680.         int *cp;
  681.         RectBottom(lrc) = RectTop(lrc);
  682.         storevideo(lrc, Bsave);
  683.         RectTop(lrc) = RectBottom(lrc) = RectBottom(rc);
  684.         storevideo(lrc, Bsave + Bwd);
  685.         cp = Bsave + Bwd * 2;
  686.         for (i = 1; i < Bht-1; i++)    {
  687.             PutVideoChar(RectLeft(rc),RectTop(rc)+i, *cp++);
  688.             PutVideoChar(RectRight(rc),RectTop(rc)+i, *cp++);
  689.         }
  690.         free(Bsave);
  691.         Bsave = NULL;
  692.     }
  693. }
  694.  
  695. static void RemoveWindow(WINDOW wnd, int Both)
  696. {
  697.     if (PrevWindow(wnd) != NULLWND)
  698.         NextWindow(PrevWindow(wnd)) = NextWindow(wnd);
  699.     if (NextWindow(wnd) != NULLWND)
  700.         PrevWindow(NextWindow(wnd)) = PrevWindow(wnd);
  701.     if (wnd == Focus.FirstWindow)
  702.         Focus.FirstWindow = NextWindow(wnd);
  703.     if (wnd == Focus.LastWindow)
  704.         Focus.LastWindow = PrevWindow(wnd);
  705.     if (Both)    {
  706.         if (PrevWindowBuilt(wnd) != NULLWND)
  707.             NextWindowBuilt(PrevWindowBuilt(wnd)) = NextWindowBuilt(wnd);
  708.         if (NextWindowBuilt(wnd) != NULLWND)
  709.             PrevWindowBuilt(NextWindowBuilt(wnd)) = PrevWindowBuilt(wnd);
  710.         if (wnd == Built.FirstWindow)
  711.             Built.FirstWindow = NextWindowBuilt(wnd);
  712.         if (wnd == Built.LastWindow)
  713.             Built.LastWindow = PrevWindowBuilt(wnd);
  714.     }
  715. }
  716.  
  717. static void AddWindow(WINDOW wnd, int Both)
  718. {
  719.     if (Focus.FirstWindow == NULLWND)
  720.         Focus.FirstWindow = wnd;
  721.     if (Focus.LastWindow != NULLWND)
  722.         NextWindow(Focus.LastWindow) = wnd;
  723.     PrevWindow(wnd) = Focus.LastWindow;
  724.     NextWindow(wnd) = NULLWND;
  725.     Focus.LastWindow = wnd;
  726.     if (Both)    {
  727.         if (Built.FirstWindow == NULLWND)
  728.             Built.FirstWindow = wnd;
  729.         if (Built.LastWindow != NULLWND)
  730.             NextWindowBuilt(Built.LastWindow) = wnd;
  731.         PrevWindowBuilt(wnd) = Built.LastWindow;
  732.         NextWindowBuilt(wnd) = NULLWND;
  733.         Built.LastWindow = wnd;
  734.     }
  735. }
  736.  
  737. WINDOW GetFirstChild(WINDOW wnd)
  738. {
  739.     NextWindow = Built.FirstWindow;
  740.     while (NextWindow != NULLWND)    {
  741.         if (GetParent(NextWindow) == wnd)
  742.             break;
  743.         NextWindow = NextWindowBuilt(NextWindow);
  744.     }
  745.     return NextWindow;
  746. }
  747.  
  748. WINDOW GetNextChild(WINDOW wnd)
  749. {
  750.     do    {
  751.         NextWindow = NextWindowBuilt(NextWindow);
  752.         if (GetParent(NextWindow) == wnd)
  753.             break;
  754.     }    while (NextWindow != NULLWND);
  755.     return NextWindow;
  756. }
  757.  
  758. WINDOW GetLastChild(WINDOW wnd)
  759. {
  760.     NextWindow = Built.LastWindow;
  761.     while (NextWindow != NULLWND)    {
  762.         if (GetParent(NextWindow) == wnd)
  763.             break;
  764.         NextWindow = PrevWindowBuilt(NextWindow);
  765.     }
  766.     return NextWindow;
  767. }
  768.  
  769. WINDOW GetPrevChild(WINDOW wnd)
  770. {
  771.     do    {
  772.         NextWindow = PrevWindowBuilt(NextWindow);
  773.         if (GetParent(NextWindow) == wnd)
  774.             break;
  775.     }    while (NextWindow != NULLWND);
  776.     return NextWindow;
  777. }
  778.  
  779. static int InsideWindow(WINDOW wnd, int x, int y)
  780. {
  781.     RECT rc = WindowRect(wnd);
  782.     if (!TestAttribute(wnd, NOCLIP))    {
  783.         WINDOW pwnd = GetParent(wnd);
  784.         while (pwnd != NULL)    {
  785.             rc = subRectangle(rc, ClientRect(pwnd));
  786.             pwnd = GetParent(pwnd);
  787.         }
  788.     }
  789.     return InsideRect(x, y, rc);
  790. }
  791.  
  792. WINDOW inWindow(int x, int y)
  793. {
  794.     WINDOW wnd = Focus.LastWindow;
  795.     while (wnd != NULLWND)    {
  796.         if (SendMessage(wnd, INSIDE_WINDOW, x, y))
  797.             break;
  798.         wnd = PrevWindow(wnd);
  799.     }
  800.     return wnd;
  801. }
  802.  
  803. int isWindow(WINDOW wnd)
  804. {
  805.     WINDOW ws = Focus.FirstWindow;
  806.     while (ws != NULLWND)    {
  807.         if (ws == wnd)
  808.             break;
  809.         ws = NextWindow(ws);
  810.     }
  811.     return ws != NULLWND;
  812. }
  813.  
  814. int WndForeground(WINDOW wnd)
  815. {
  816.     CLASS class = FindClass(GetClass(wnd));
  817.     if (classdefs[class].fg == NULL)
  818.         class = FindClass(GetClass(GetParent(wnd)));
  819.     return *classdefs[class].fg;
  820. }
  821.  
  822. int WndBackground(WINDOW wnd)
  823. {
  824.     CLASS class = FindClass(GetClass(wnd));
  825.     if (classdefs[class].bg == NULL)
  826.         class = FindClass(GetClass(GetParent(wnd)));
  827.     return *classdefs[class].bg;
  828. }
  829.  
  830. int FrameForeground(WINDOW wnd)
  831. {
  832.     CLASS class = FindClass(GetClass(wnd));
  833.     if (classdefs[class].fbg != NULL)
  834.         return *classdefs[class].ffg;
  835.     else
  836.         return WndForeground(wnd);
  837. }
  838.  
  839. int FrameBackground(WINDOW wnd)
  840. {
  841.     CLASS class = FindClass(GetClass(wnd));
  842.     if (classdefs[class].fbg != NULL)
  843.         return *classdefs[class].fbg;
  844.     else
  845.         return WndBackground(wnd);
  846. }
  847.  
  848. int SelectForeground(WINDOW wnd)
  849. {
  850.     CLASS class = FindClass(GetClass(wnd));
  851.     return *classdefs[class].sfg;
  852. }
  853.  
  854. int SelectBackground(WINDOW wnd)
  855. {
  856.     int class = FindClass(GetClass(wnd));
  857.     return *classdefs[class].sbg;
  858. }
  859.  
  860. void SetStandardColor(WINDOW wnd)
  861. {
  862.     foreground = WndForeground(wnd);
  863.     background = WndBackground(wnd);
  864. }
  865.  
  866. void SetReverseColor(WINDOW wnd)
  867. {
  868.     foreground = SelectForeground(wnd);
  869.     background = SelectBackground(wnd);
  870. }
  871.  
  872. void SetClassColors(CLASS class)
  873. {
  874.     foreground = *classdefs[class].fg;
  875.     background = *classdefs[class].bg;
  876. }
  877.  
  878.  
  879.